#include "TCP_socket.hpp"

using namespace mycode;

// 构造函数
TCP::TCP(const string ip, const uint16_t port)
    : _socket(-1), _ip(ip), _port(port)
{
    // 设置socket文件描述符
    _socket = socket(AF_INET, SOCK_STREAM, 0);
    if (_socket < 0)
    {
        LOG_FATAL("socket error");
        exit(SOCKETERR);
    }

    // 设置socket地址
    _paddr = new sockaddr_in;
    _paddr->sin_family = AF_INET;
    _paddr->sin_addr.s_addr = inet_addr(ip.c_str());
    _paddr->sin_port = htons(port);
}

// 绑定socket
void TCP::TCP_Bind()
{
    int ret = bind(_socket, reinterpret_cast<sockaddr *>(_paddr), sizeof(*_paddr));
    if (ret < 0)
    {
        LOG_ERROR("bind error, err code: %d, err reason: %s", errno, strerror(errno));
        exit(BINDERR);
    }
}

// 设置监听模式
void TCP::TCP_Listen()
{
    if (listen(_socket, 50) < 0)
    {
        LOG_ERROR("listen err, err code: %d, err reason: %s", errno, strerror(errno));
        exit(LISTENERR);
    }
}

// 接收请求
int TCP::TCP_Accept(struct sockaddr *peer, socklen_t *len)
{
    int acpt_socket = accept(_socket, peer, len);
    if (acpt_socket < 0)
    {
        LOG_ERROR("accept error, err code: %d, err reason: %s", errno, strerror(errno));
    }
    return acpt_socket;
}

// 建立连接
void TCP::TCP_Connect()
{
    int ret = connect(_socket, reinterpret_cast<sockaddr *>(_paddr), sizeof(*_paddr)) < 0;
    if (ret < 0)
    {
        LOG_ERROR("connect error, socket: %d", _socket);
        exit(CONNECTERR);
    }
}

// 获取socket
int TCP::getSocket()
{
    return _socket;
}

// 服务器初始化
void TCP::server_init()
{
    // 绑定socket
    TCP_Bind();
    // 设置监听模式
    TCP_Listen();
    // 初始化文件描述符集
    for (int i = 0; i < MAX_FD; i++)
    {
        _fdset[i] = defaultfd;
    }
    _fdset[0] = _socket;
}

void datahander(int fd)
{
    char buff[1024];
    recv(fd, buff, sizeof(buff), 0);
    cout << buff << endl;
}

void TCP::HanderEvent(fd_set *pfset)
{
    // 处理
    int tem[2];
    for (int i = 0; i < MAX_FD; i++)
    {
        if (_fdset[i] == defaultfd)
            continue;
        // 有新连接
        else if (FD_ISSET(_fdset[i], pfset) && _fdset[i] == _socket)
        {
            // 获取通信socket
            struct sockaddr_in peer; // 记录客户端地址
            socklen_t len = sizeof(peer);
            int cSocket = TCP_Accept(reinterpret_cast<sockaddr *>(&peer), &len);
            for (int i = 0; i < MAX_FD; i++)
            {
                if (_fdset[i] == defaultfd)
                {
                    _fdset[i] = cSocket;
                    break;
                }
            }
        }
        // 有客户端数据
        else if (FD_ISSET(_fdset[i], pfset))
        {
            datahander(_fdset[i]);
        }
    }
}

// 服务器开始
void TCP::server_start()
{
    while (true)
    {
        // 合法文件描述符
        int maxfd = _fdset[0];
        fd_set fset;
        for (int i = 0; i < MAX_FD; i++)
        {
            if (_fdset[i] == defaultfd)
                continue;
            else
            {
                FD_SET(_fdset[i], &fset);
                if (_fdset[i] > maxfd)
                    maxfd = _fdset[i];
            }
        }

        // select非阻塞
        timeval overtime;
        overtime.tv_sec = 1;
        overtime.tv_usec = 0;
        int n = select(maxfd + 1, &fset, nullptr, nullptr, &overtime);
        if (n < 0)
        {
            LOG_ERROR("select error, err code: %d, err reason: %s", errno, strerror(errno));
            break;
        }
        if (n == 0)
        {
            LOG_INFO("timeout...");
        }
        if (n > 0)
        {
            LOG_INFO("event ready!");
            HanderEvent(&fset);
        }
    }
}

// 析构函数
TCP::~TCP()
{
    close(_socket);
}
